package apibasej.db.sql.wrapper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import apibasej.db.metadata.Col;
import apibasej.db.metadata.Tab;

public class WrapperTabJoin extends WrapperTab {
	
	private WrapperTab tabJoinBefore;// se quiser determinar qual tab do select adicionada que fará o vínculo com esta
	private List<Col<?>[]> colsLinkJoin;
	
	public WrapperTabJoin(Tab tab) {
		super(tab);
	}

	
	public void setColsLinkJoin(List<Col<?>[]> colsLinkJoin) {
		this.colsLinkJoin = colsLinkJoin;
	}
	public void setColsLinkJoin(Col<?>[]... colsLinkJoin) {
		this.colsLinkJoin = Arrays.asList(colsLinkJoin);
	}
	
	//caso o vínculo seja somente por uma coluna
	public <T> void setColsLinkJoin(Col<T> col1, Col<T> col2) {
		setColsLinkJoin(new Col<?>[]{col1,col2});
	}
	
	public List<Col<?>[]> getColsLinkJoin(WrapperSQL wrapperSQL) throws SQLWrapperException{
		if(colsLinkJoin==null || colsLinkJoin.size()==0) {
			colsLinkJoin = this.getTab().getLinksForTab(getTabJoinBefore(wrapperSQL).getTab());
		}
		return colsLinkJoin;
	}
	
	
	public WrapperTab getTabJoinBeforeSetted(){
		return tabJoinBefore;
	}
	
	public WrapperTab getTabJoinBefore(WrapperSQL wrapperSQL) throws SQLWrapperException {
		if(tabJoinBefore==null) {
			// se tem vínculo com a tabela root
			WrapperTab wtRoot = wrapperSQL.getWrapperTabRoot();
			if(!wtRoot.isIgnoreAutoJoinForThis()){
				ArrayList<Col<?>[]> colsJoin = this.getTab().getLinksForTab(wtRoot.getTab());
				if(colsJoin!=null && colsJoin.size()>0){
					tabJoinBefore = wrapperSQL.getWrapperTabRoot();
					colsLinkJoin = colsJoin;
				}
			}
			// se não achou na root procura nas outras tabelas adicionadas, pelas primeiras adicionadas primeiro ...
			if(tabJoinBefore==null){
				for(WrapperTab tJoin : wrapperSQL.getTabsJoin()){
					if(!tJoin.isIgnoreAutoJoinForThis()){
						ArrayList<Col<?>[]> colsJoin = this.getTab().getLinksForTab(tJoin.getTab());
						if(colsJoin!=null && colsJoin.size()>0){
							tabJoinBefore = tJoin;
							colsLinkJoin = colsJoin;
							break;
						}
					}
				}
			}
			if(tabJoinBefore==null) {
				throw new SQLWrapperException("Foreing keys not found in tables added before. Tab: "+this.getTab().getName());
			}
			if(colsLinkJoin==null) {
				throw new SQLWrapperException("Columns join not found. Tab this: "+getTab().getName()+", Tab join before: "+tabJoinBefore.getTab().getName());
			}
		}
		return tabJoinBefore;
	}
	public void setTabJoinBefore(WrapperTab tabJoinBefore) {
		this.tabJoinBefore = tabJoinBefore;
	}
	
	
	
	
	// TODO criar classe para todas consts !!!
	
	//http://en.wikipedia.org/wiki/Join_(SQL)
	public static final String INNER_JOIN = "INNER JOIN";
	public static final String LEFT_JOIN = "LEFT JOIN";
	//TODO colocar constantes e métodos para os outros tipos de join ...
	public static final String DEFAULT_STR_JOIN = LEFT_JOIN;
	
	private String strTypeJoin = null;
	public String getStrTypeJoin() {
		if(strTypeJoin==null) {
			return DEFAULT_STR_JOIN;
		}
		return strTypeJoin;
	}
	public void setStrTypeJoin(String strTypeJoin) {
		this.strTypeJoin = strTypeJoin;
	}

	
	
	public void setInnerJoin(){
		setStrTypeJoin(INNER_JOIN);
	}
	public void setLeftJoin(){
		setStrTypeJoin(LEFT_JOIN);
	}
	public boolean isInnerJoin(){
		return INNER_JOIN.equalsIgnoreCase(getStrTypeJoin().trim());
	}
	public boolean isLeftJoin(){
		return LEFT_JOIN.equalsIgnoreCase(getStrTypeJoin().trim());
	}

	
}
